#include <iostream>
#include <string>

#include <websocketpp/server.hpp>
#include <websocketpp/config/asio_no_tls.hpp>

void http_callback(websocketpp::server<websocketpp::config::asio>& ws, websocketpp::connection_hdl hdl)
{
    websocketpp::server<websocketpp::config::asio>::connection_ptr con = ws.get_con_from_hdl(hdl);

    std::string req_body = con->get_request_body();
    websocketpp::http::parser::request req = con->get_request();

    //打印http的请求方法和uri
    std::cout << "post: " << req.get_method() << "  uri: " << req.get_uri() << std::endl;
    //打印请求正文
    std::cout << "body: " << req_body << std::endl;

    // 给客户端返回一个hello world的页面
    std::string res_body = "<html><body><h1>Hell Bit</h1></body></html>";
    con->set_body(res_body);
    con->append_header("Content-Type", "text/html");
    con->set_status(websocketpp::http::status_code::value::ok);

}
void wsopen_callback(websocketpp::server<websocketpp::config::asio>& ws, websocketpp::connection_hdl hdl)
{
    std::cout << "websocket握手成功!!!" << std::endl;
}
void wsclose_callback(websocketpp::server<websocketpp::config::asio>& ws, websocketpp::connection_hdl hdl)
{
    std::cout << "websocket链接断开!!!" << std::endl;
}

void wsmessage_callback(websocketpp::server<websocketpp::config::asio>& ws, websocketpp::connection_hdl hdl, websocketpp::server<websocketpp::config::asio>::message_ptr msg)
{
    websocketpp::server<websocketpp::config::asio>::connection_ptr con = ws.get_con_from_hdl(hdl);
    std::string message = msg->get_payload();
    std::cout << "client say: " << message << std::endl;

    message = "收到你发的消息了";
    con->send(message, websocketpp::frame::opcode::value::text);
}


// 构建websocket服务器
int main()
{
    // 1、实例化server对象
    websocketpp::server<websocketpp::config::asio> ws;
    // 2、设置日志等级
    ws.set_access_channels(websocketpp::log::alevel::none);
    // 3、初始化asio调度器
    ws.init_asio();
    ws.set_reuse_addr(true); //函数的作用：服务器在上一次关闭后，可以立即重启并重新绑定同一个端口，不会报 “Address already in use”
    // 4、设置回调函数
    // ws 是一个 非拷贝类型对象（websocketpp::server<> 内部禁用了拷贝构造），而 std::bind 默认会拷贝它
    ws.set_open_handler(bind(wsopen_callback, std::ref(ws), std::placeholders::_1)); //websocket握手成功回调处理函数
    ws.set_close_handler(bind(wsclose_callback, std::ref(ws), std::placeholders::_1)); //websocket链接关闭回调处理函数
    ws.set_message_handler(bind(wsmessage_callback, std::ref(ws), std::placeholders::_1, std::placeholders::_2)); //websocket收到消息的回调处理函数
    ws.set_http_handler(bind(http_callback, std::ref(ws), std::placeholders::_1)); // http请求回调处理函数
    // 5、设置监听端口
    ws.listen(8080);
    // 6、开始获取新链接
    ws.start_accept();
    // 7、启动服务器
    ws.run();

    return 0;
}
